﻿using Grpc.Core;
using Microsoft.AspNetCore.Authorization;
using Wen.GrpcService.Entity;

namespace Wen.GrpcService.Services;

[Authorize]
public class FileService(IConfiguration config, IFreeSql freeSql) : Fileer.FileerBase
{
    private readonly string _storagePath = config["SysSettings:FilePath"]; // 文件存储目录

    /// <summary>
    /// 文件上传
    /// </summary>
    /// <param name="requestStream"></param>
    /// <param name="context"></param>
    /// <returns></returns>
    public override async Task<UploadResponse> UploadFile(IAsyncStreamReader<FileChunk> requestStream, ServerCallContext context)
    {
        var sysfile = new SysFile();
        //插入数据
        freeSql.Insert<SysFile>().AppendData(sysfile).ExecuteAffrows();

        //string? fileName = null;
        //using (var memoryStream = new MemoryStream())
        //{
        //    await foreach (var chunk in requestStream.ReadAllAsync())
        //    {
        //        if (fileName == null)
        //        {
        //            fileName = chunk.FileName;
        //        }
        //        memoryStream.Write(chunk.Content.ToByteArray());
        //    }

        //    if (fileName == null)
        //    {
        //        return new UploadResponse { Success = false, Message = "文件名为空" };
        //    }

        //    string filePath = Path.Combine(_storagePath, fileName);
        //    await File.WriteAllBytesAsync(filePath, memoryStream.ToArray());
        //}

        //return new UploadResponse { Success = true, Message = "文件上传成功" };


        try
        {
            FileStream fileStream = null;
            // 读取流中的文件块
            await foreach (var chunk in requestStream.ReadAllAsync())
            {
                if (fileStream is null)
                {
                    sysfile.Name = chunk.FileName;
                    sysfile.Ext = Path.GetExtension(chunk.FileName);                    

                    var folder = Path.Combine(_storagePath, sysfile.Folder);
                    if (!Directory.Exists(folder))
                        Directory.CreateDirectory(folder);

                    var savePath = Path.Combine(folder, sysfile.Id.ToString() + sysfile.Ext);

                    fileStream = new FileStream(savePath, FileMode.Create, FileAccess.Write);
                }
                sysfile.SizeKb += chunk.Content.Length / 1024;
                // 写入文件内容
                if (chunk.Content.Length > 0)
                {
                    await fileStream.WriteAsync(chunk.Content.ToByteArray());
                }
            }

            freeSql.Update<SysFile>().SetSource(sysfile).ExecuteAffrows();
            fileStream?.Dispose();
            return new UploadResponse
            {
                Success = true,
                Message = $"File {sysfile.Name} uploaded successfully."
            };
        }
        catch (Exception ex)
        {
            return new UploadResponse
            {
                Success = false,
                Message = $"Upload failed: {ex.Message}"
            };
        }
    }
    public override async Task DownloadFile(DownloadRequest request, IServerStreamWriter<FileChunk> responseStream, ServerCallContext context)
    {
        string filePath = Path.Combine(_storagePath, request.FileName);

        if (!File.Exists(filePath))
        {
            throw new RpcException(new Status(StatusCode.NotFound, "文件未找到"));
        }

        byte[] fileBytes = await File.ReadAllBytesAsync(filePath);
        const int chunkSize = 64 * 1024; // 每块 64KB

        for (int i = 0; i < fileBytes.Length; i += chunkSize)
        {
            var chunk = new FileChunk
            {
                Content = Google.Protobuf.ByteString.CopyFrom(fileBytes, i, Math.Min(chunkSize, fileBytes.Length - i))
            };
            await responseStream.WriteAsync(chunk);
        }
    }
}